package multiThreaded;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * Url buffer for the web spider.
 * @author DoubleS
 * @version 1.0
 */
public class UrlBuffer
{
  /**
   * Maximum number of unvisited links to be buffered. 
   */
  public static final int MAX_URL_BUFFER = 1500;
  
  /**
   * The list of already visited links.
   */
  private List<String> my_visited_links;
  
  /**
   * The queue of unvisited links.
   */
  private ArrayBlockingQueue<String> my_unvisited_links;
  
  /**
   * Construct an empty UrlBuffer.
   */
  public UrlBuffer()
  {
    my_visited_links = new LinkedList<String>();
    my_unvisited_links = new ArrayBlockingQueue<String>(MAX_URL_BUFFER);
  }
  
  /**
   * Add the link into the list of already visited pages and make sure that there's no
   * duplicates in the list.
   * @param the_link The link.
   */
  public void addToVisitedPages(final String the_link)
  {
    if (!my_visited_links.contains(the_link))
    {
      my_visited_links.add(the_link);
    }
  }
  
  /**
   * Add the link to the unvisited pages if it's not already in the list of visited and 
   * unvisited pages.
   * @param the_link The links.
   */
  public void addToUnvisitedPages(final String the_link)
  {
    if (!(my_visited_links.contains(the_link) || my_unvisited_links.contains(the_link)))
    {
      try
      {
        my_unvisited_links.put(the_link);
      }
      catch (final InterruptedException e)
      {
        e.printStackTrace();
      }
    }
  }
  
  /**
   * Return the next unvisited link from the list of unvisited pages. Then add that link
   * to the list of already visited pages.
   * @return The next unvisited link from the list of unvisited pages.
   */
  public String retrieveAnUnvisitedLink()
  {
    String the_link = null;
    
    try
    {
      the_link = my_unvisited_links.take();
      my_visited_links.add(the_link);
    }
    catch (final InterruptedException e)
    {
      e.printStackTrace();
    }
    
    return the_link;
  }
  
  /**
   * 
   * @param the_link The link.
   * @return True if the link is already visited. False otherwise.
   */
  public boolean isAlreadyVisited(final String the_link)
  {
    return my_visited_links.contains(the_link);
  }
  
  /**
   * 
   * @return The total number of links which have been encountered so far.
   */
  public int getTotalLinks()
  {
    return my_visited_links.size() + my_unvisited_links.size();
  }
  
  /**
   * 
   * @return If there's no more links in the unvisited pages list. False otherwise.
   */
  public boolean isEmpty()
  {
    return my_unvisited_links.isEmpty();
  }
  
  /*
   * For testing purpose
   * 
  public ArrayBlockingQueue getUnvisitedLinks()
  {
    return my_unvisited_links;
  }*/
  
  /**
   * 
   * @return Number of unvisited pages.
   */
  public int getNumVisitedPages()
  {
    return my_visited_links.size();
  }
}
